package com.wang.transfer.util.xmlToList;

import com.wang.transfer.util.propertiesToJson.treeJson.exception.InputOutputFileException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Stack;

/**
 * xml文件 转换为 对象
 * {{tag: '', content: '', child: [{tag: '', content: '', child: []}}, {tag: '', content: '', child: []}]}
 */
@Slf4j
public class XmlToObj {

    private final Logger logger = LoggerFactory.getLogger(XmlToObj.class);

    // 判别循环内所有child都走过
    private static Boolean forTag = false;
    // 栈 存放节点
    private final Stack<String> stack = new Stack<>();
    // XmlObj 最大标签
    private final XmlObj xml = new XmlObj();

    // 输入文件
    private String INPUT_FILE = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\daily-platform-module\\platform-module-transfer\\src\\main\\resources\\test\\menu.xml";

    /**
     * 配置输入文件
     */
    public void setINPUT_FILE(String INPUT_FILE) {
        if (StringUtils.hasText(INPUT_FILE)) {
            this.INPUT_FILE = INPUT_FILE;
        }
    }

    /**
     * 执行方法
     */
    public void execute() throws InputOutputFileException {
        readFile();
        writeFile();
    }

    /**
     * 读文件方法
     */
    private void readFile() throws InputOutputFileException {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(INPUT_FILE));
            String line;
            while ((line = reader.readLine()) != null) {
                line = checkLine(line);
                if (line == null) continue;
                Boolean bol = checkNode(line);
            }
        } catch (IOException e) {
            throw new InputOutputFileException("输入文件不存在！");
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 写方法
     */
    private void writeFile() {
        logger.info(String.valueOf(xml));
    }

    /**
     * 判断是否为开始、结束标签、内容
     */
    private Boolean checkNode(String line) {
        // 结束标签的值
        String endNode = line.contains("</") ? line.substring(line.indexOf("</") + 2, line.lastIndexOf(">")) : null;
        String subLine = null;
        String enn = null;
        if (endNode != null) {
            enn = "</" + endNode + ">";
            subLine = line.substring(0, line.lastIndexOf(enn));
        }
        // 开始标签的值
        String startNode = null;
        // 内容
        String content = null;
        if (endNode != null && subLine.contains("<")) {
            startNode = line.substring(line.indexOf("<") + 1, line.indexOf(">"));
            String stn = "<" + startNode + ">";
            content = line.substring(line.indexOf(stn) + stn.length(), line.lastIndexOf(enn) - 1);
        } else if (endNode == null && line.contains("<")) {
            startNode = line.substring(line.indexOf("<") + 1, line.lastIndexOf(">"));
            String stn = "<" + startNode + ">";
            if (!line.equals(stn)) content = line.substring(line.indexOf(stn) + 1);
        } else {
            content = line;
        }
        if (stack.empty()) {
            // 此时Line为最大标签，直接存入到栈中
            stack.add(startNode);
            xml.setTag(startNode);
        } else if (startNode == null && endNode != null && stack.size() > 1) {
            // 非最大结束标签
//            logger.info("xml=>{}", xml.toString());
            stack.pop();
//            XmlObj obj = new XmlObj();
//            XmlObj obj1 = recursionForNode(xml, obj);
        } else if ((startNode != null && stack.size() >= 1) || StringUtils.hasText(content)) {
            // 非最大开始标签 或 内容
            XmlObj obj = new XmlObj();
            obj.setTag(startNode);
            obj.setContent(content);
            recursionForNode(xml, obj);
        }
        return false;
    }

    /**
     * 递归查找节点插入节点
     */
    private Boolean recursionForNode(XmlObj xmlObj, XmlObj obj) {
        logger.info("栈顶元素：{}", stack.peek());
        logger.info("栈内元素：{}", Arrays.toString(stack.toArray()));
        boolean bol = false;
        if (!xmlObj.getTag().equals(stack.peek())) {
            // 没找到父节点，向下递归查找
            for (XmlObj o : xmlObj.getXmlObjs()) {
                bol = recursionForNode(o, obj);
            }
        } else {
            if (obj.getTag() != null && !obj.getExist()) {
                // 开始标签和结束标签不同时在一行时
                stack.add(obj.getTag());
            }
            if (obj.getTag() == null) {
                xmlObj.setContent(obj.getContent());
            } else {
                xmlObj.getXmlObjs().add(obj);
            }
            return true;
        }
        return false;
    }

    /**
     * 校验Line
     */
    private String checkLine(String line) {
        // 去除行中的空格
        line = line.replaceAll("\\s", "");
        // 如果为空，则转到下一行
        if (!StringUtils.hasLength(line)) {
            return null;
        }
        // 排除注释
        if ("<!--".equals(line.substring(0, 4)) && "-->".equals(line.substring(line.length() - 3))) {
            return null;
        }
        return line;
    }
}
